package com.kalvan.core.mybatis;


import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.kalvan.core.exception.BizException;
import com.kalvan.core.utils.Sysdate;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.exceptions.TooManyResultsException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Condition;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.List;
import java.util.Map;

/**
 * 基于通用MyBatis Mapper插件的Service接口的实现
 *
 * @author chenliang
 */
@Slf4j
public abstract class BaseService<T> implements IBaseService<T> {

    @Autowired
    protected IBaseMapper<T> mapper;
    /**
     * 当前泛型真实类型的Class
     */
    private Class<T> modelClass;

    public BaseService() {
        // 获得具体model，通过反射来根据属性条件查找数据
        ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
        modelClass = (Class<T>) pt.getActualTypeArguments()[0];
    }

    /**
     * 转换范围参数
     *
     * @param params      参数map
     * @param attrName    参数名
     * @param isTime      是否为时间范围
     * @param required    是否必须
     */
    protected static void convertBetweenParams(Map<String, String> params,String attrName, boolean isTime, boolean required) {
        String betweenTemp = params.get(attrName);
        if (StringUtils.isNotBlank(betweenTemp) && !",".equals(betweenTemp)) {
            String[] times = betweenTemp.split(",");
            if (isTime) {
                //时间类
                params.put(attrName + "Begin", StringUtils.rightPad(times[0], 19, " 00:00:00"));
                if (times.length > 1) {
                    params.put(attrName + "End", StringUtils.rightPad(times[1], 19, " 00:00:00"));
                } else {
                    params.put(attrName + "End", Sysdate.getTimeStr(false));
                }
            } else {
                //数字类
                params.put(attrName + "Begin", times[0]);
                if (times.length > 1) {
                    params.put(attrName + "End", times[1]);
                } else {
                    params.put(attrName + "End", 999999999 + "");
                }
            }
        } else if (required) {
            //如果没有传参同时又必填提示异常
            throw new BizException(attrName + "不能为空");
        }
    }

    @Override
    public int add(T model) {
        return mapper.insertSelective(model);
    }

    @Override
    public int add(List<T> models) {
        return mapper.insertList(models);
    }

    @Override
    public int delete(Object id) {
        return mapper.deleteByUk(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteBatch(Object[] ids) {
        int resultNum = 0;
        for (Object id : ids) {
            resultNum = resultNum + mapper.deleteByUk(id);
        }
        return resultNum;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int auditingBatch(Object[] ids, boolean pass) {
        int resultNum = 0;
        for (Object id : ids) {
            T t = mapper.selectByUk(id);
            //TODO 更新审核状态
            resultNum = resultNum + mapper.updateByUkSelective(t);
        }
        return resultNum;
    }

    @Override
    public int edit(T model) {
        return mapper.updateByUkSelective(model);
    }

    @Override
    public T findById(Object id) {
        return mapper.selectByUk(id);
    }

    @Override
    public T findBy(String fieldName, Object value) throws TooManyResultsException {
        try {
            T model = modelClass.newInstance();
            Field field = modelClass.getDeclaredField(fieldName);
            field.setAccessible(true);
            field.set(model, value);
            return mapper.selectOne(model);
        } catch (ReflectiveOperationException e) {
            throw new TooManyResultsException(e.getMessage(), e);
        }
    }

    @Override
    public List<T> findByCondition(Condition condition) {
        return mapper.selectByCondition(condition);
    }

    @Override
    public List<T> findAll() {
        return mapper.selectAll();
    }

    @Override
    public Page<T> queryPage(PageInfo page, Map<String, String> params) {
        processParams(params);
        try {
            PageHelper.startPage(page.getPage(), page.getLimit());
            return (Page<T>) mapper.queryPage(params);
        } finally {
            PageHelper.clearPage();
        }
    }

    @Override
    public Map<String, String> querySum(Map<String, String> params) {
        processParams(params);
        return mapper.querySum(params);
    }


    /**
     * 处理查询参数
     *
     * @param params 查询参数
     */
    public abstract void processParams(Map<String, String> params);
}